import os
from datetime import datetime, timedelta
import tqdm
from dateutil.relativedelta import relativedelta
import requests
import uvicorn
import random
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware


def get_cookie():
    jsessionid = requests.post('http://10.84.4.74/yyqer/login.jsp',
                               data={'name': 'wlx2023.jhyt',
                                     'pwd': '65154E8BFDC8C394424E31A390816707047B38D16805AD551D36D9862A3003C6'},
                               verify=False).cookies.get_dict()['JSESSIONID']
    cookie = f'userName=wlx2023.jhyt; password=; JSESSIONID={jsessionid}'
    header = {"Cookie": cookie}
    # with open("cookie.txt", "r") as f:
    #     cookie = f.read()
    # return {"Cookie": cookie}
    return header


def get_next_pro(pro_run_date, pro_day_date, notes):
    """
    机理模型获取单井次月预估产量
    """
    # 连续生产时间都为0，代表未投产
    if sum(pro_run_date) == 0:
        return 0
    # 计算连续关井的最大天数
    max_consecutive_shutdown_days = 0
    current_consecutive_shutdown = 0
    for day in pro_run_date:
        if day == 0:
            current_consecutive_shutdown += 1
            max_consecutive_shutdown_days = max(max_consecutive_shutdown_days, current_consecutive_shutdown)
        else:
            current_consecutive_shutdown = 0
    # 生产时率
    production_rate = round((sum(pro_run_date) / len(pro_run_date) * 24), 2)
    if production_rate == 1.0:
        base_production = sum(pro_day_date[-5:]) / 5  # 近5天的平均产量
    elif production_rate >= 0.95:
        temp_notes, temp_pro = notes[-15:], pro_day_date[-15:]
        fil_pro = [temp_pro[i] for i, note in enumerate(temp_notes) if "关井" not in note]
        base_production = sum(fil_pro) / len(fil_pro)
    elif production_rate >= 0.7:
        if max_consecutive_shutdown_days <= 3:
            temp_pro = [pro_day_date[i] for i, note in enumerate(notes) if "压裂" not in note]
        else:
            temp_pro = [pro_day_date[i] for i, note in enumerate(notes) if "压裂" not in note and pro_day_date[i] != 0]
        base_production = sum(temp_pro) / len(temp_pro)
    elif production_rate >= 0.5:
        if max_consecutive_shutdown_days <= 4:
            temp_pro = [pro_day_date[i] for i, note in enumerate(notes) if "压裂" not in note]
        else:
            temp_pro = [pro_day_date[i] for i, note in enumerate(notes) if "压裂" not in note and pro_day_date[i] != 0]
        base_production = sum(temp_pro) / len(temp_pro)
    elif production_rate >= 0.2:
        if max_consecutive_shutdown_days <= 6:
            temp_pro = [pro_day_date[i] for i, note in enumerate(notes) if "压裂" not in note]
        else:
            temp_pro = [pro_day_date[i] for i, note in enumerate(notes) if "压裂" not in note and pro_day_date[i] != 0]
        base_production = sum(temp_pro) / len(temp_pro)
    else:
        if max_consecutive_shutdown_days <= 22:
            temp_pro = [pro_day_date[i] for i, note in enumerate(notes) if "压裂" not in note]
        else:
            temp_pro = [pro_day_date[i] for i, note in enumerate(notes) if "压裂" not in note and pro_day_date[i] != 0]
        base_production = sum(temp_pro) / len(temp_pro)
    return base_production


def get_ins_pro(notes, oil_pressure, casing_pressure, line_pressure):
    """
    计算单井提产产能水平
    """
    keys_1 = ["压力恢复", "敞放", "出砂"]
    note_str = ",".join(notes)
    # 检查 notes 中是否存在 keys_1 的任意一个关键词
    if any(key in note_str for key in keys_1):
        return 0
    else:
        aver_oil = round(sum(oil_pressure) / len(oil_pressure), 2)
        aver_cas = round(sum(casing_pressure) / len(casing_pressure), 2)
        aver_lin = round(sum(line_pressure) / len(line_pressure), 2)

        # 区分增压井-外输井
        if "增压开采" in note_str:
            # print("增压井")
            pro_temp = min(aver_oil, aver_cas) - 1
            if 0.5 <= pro_temp < 1:
                return round(random.uniform(0.8, 1.3), 2)
            elif pro_temp >= 1:
                return round(random.uniform(1.3, 1.9), 2)
            else:
                return 0
        else:
            # print("外输井")
            pro_temp = aver_oil - aver_lin
            if 1 <= pro_temp < 2:
                return round(random.uniform(0.8, 1.3), 2)
            elif pro_temp >= 2:
                return round(random.uniform(1.9, 2.5), 2)
            else:
                return 0


def get_info():
    # 获取header
    header = get_cookie()
    well_url = "http://10.84.4.74/yyqer/public/wellList.jsp?table=AZ041"
    response = requests.post(well_url, headers=header).json()["jhs"]
    tq_data = tqdm.tqdm(response)

    res = "|井号|区块|投产日期|次月能达到的产能水平（方）|能提产量（万方）|\n" + "｜---" * 5 + "\n"
    for data in tq_data:
        """
        dwmc: "涪陵公司"
        fq: "焦石坝加密"
        jh: "焦页13-5HF"
        jlzh: "13#东集气站"
        qkdy: "焦石坝"
        tcrq: "20200705"
        xzq: "涪陵区"
        """
        if data["dwmc"] != "涪陵公司":
            continue
        well_name = data["jh"]
        block = data["qkdy"]
        product_date = data["tcrq"]

        # 获取单井生产数据
        current_date = datetime.now().strftime("%Y-%m-%d")
        previous_date = (datetime.now() - relativedelta(months=1)).strftime("%Y-%m-%d")
        pro_url = f"http://10.84.4.74/yyqer/scbb/r_djsj_json.jsp?tz=&srq={previous_date}&erq={current_date}&jh={well_name}"
        sin_data = requests.post(pro_url, headers=header).json()

        # 如果没有数据，该井不计入
        if "errcode" in sin_data:
            increase_pro_1 = increase_pro_2 = 0
        else:
            # 获取生产时间/日产量/备注
            pro_run_date, pro_day_date, notes = [], [], []
            # 获取油压/套压/输压
            oil_pressure, casing_pressure, line_pressure = [], [], []

            for x in sin_data["data"][:-1]:
                pro_run_date.append(float(x[1]) if x[1] != '' else 0)
                pro_day_date.append(float(x[6]) if x[6] != '' else 0)
                notes.append(x[-1])
                oil_pressure.append(float(x[3]) if x[3] != '' else 0)
                casing_pressure.append(float(x[2]) if x[2] != '' else 0)
                line_pressure.append(float(x[4]) if x[4] != '' else 0)

            # 计算次月生产水平
            try:
                increase_pro_1 = get_next_pro(pro_run_date, pro_day_date, notes)
            except Exception as e:
                increase_pro_1 = 0
            # 计算能提产多少万方
            try:
                increase_pro_2 = get_ins_pro(notes, oil_pressure, casing_pressure, line_pressure)
            except Exception as e:
                increase_pro_2 = 0

        res += f"|{well_name}|{block}|{product_date}|{increase_pro_1}|{increase_pro_2}|\n"
    return res

def get_new_info():
    """
    候选井:当前配产<最大配产
        第一批:当前配产<合理配产，提至合理配产
        第二批:合理配产<当前配产<最大配产，提至min(当前配产+2，最大配产)
    候选井:当前配产>合理配产
        第一批:当前配产>=最大配产>合理配产，降至 min(当前配产-2，合理配产)
        第二批:最大配产>当前配产>合理配产，降至合理配产
    """
    # 获取header
    header = get_cookie()
    data_now = datetime.now().date() - timedelta(days=1)
    url = f"http://10.84.4.74/yyqer/kfdtgl/clgl/pczb_json.jsp?rq={data_now}"
    response = requests.post(url, headers=header).json()["res"]
    tq_data = tqdm.tqdm(response)
    # 井号，合理配产，当前配产，最大配产，备注
    up_data1 = [] #数组
    up_data2 = []
    down_data = []
    for x in tq_data:
        x = [x[0], float(x[1]), float(x[2]), float(x[3]) ,x[5]]
        # 当前产量为0的，过滤掉
        if x[2] == 0 or x[3] == 10 or x[1] ==10:
            continue

        if x[2] < x[3]:
            # 提产井
            # 排除间开井
            if x[4] == "间开井":
                continue
            if x[2] < x[1] and (0.5 < x[1]-x[2] < 10):
                up_value = random.uniform(1.5,3) if x[1]-x[2] >3 else  x[1]-x[2] #如果可提产量大于3，则变为[1.5,3]之间的随机数
                up_data1.append( [x[0],x[2],up_value,x[4]])
            elif x[1] < x[2] < x[3] and (0.5 < min(x[2] + 2, x[3])-x[2] < 10):
                up_value = random.uniform(1.5, 3) if min(x[2] + 2, x[3]) > 3 else min(x[2] + 2, x[3])
                up_data2.append( [x[0],x[2],min(x[2] + 2, x[3])-x[2],x[4]] )
        elif x[2] > x[1]:
            # 降产井
            if x[2] >= x[3] > x[1]:
                if min(x[2] - 2, x[1]) > 0:
                    down_data.append( [x[0],x[2],x[2] - min(x[2] - 2, x[1]) ,x[4]] )
            elif x[3] > x[2] > x[1]:
                down_data.append( [x[0],x[2],x[2] - x[1],x[4]] )
    #随机选择两口间开井
    jk_list = [
        ["焦页38-1HF", 0, 1.2, "间开井"],
        ["焦页143-1HF", 0, 1.5, "间开井"],
        ["焦页156-1HF", 0, 1.6, "间开井"],
        ["焦页156-3HF", 0, 1.4, "间开井"],
        ["焦页148-1HF", 0, 1.0, "间开井"],
        ["焦页22-1HF", 0, 1.9, "间开井"],
        ["焦页106-2HF", 0, 2.4, "间开井"],
        ["焦页156-S1HF", 0, 1.3, "间开井"],
        ["焦页172-3HF", 0, 1.5, "间开井"],
        ["焦页84-6HF", 0, 2.8, "间开井"]
    ]
    numbers = random.sample(range(10), 2)
    up_data1.append(jk_list[numbers[0]])
    up_data1.append(jk_list[numbers[1]])

    #排序
    up_data1 = sorted(up_data1,key = lambda x:x[2],reverse=True)
    up_data2 = sorted(up_data2, key=lambda x: x[2], reverse=True)
    down_data = sorted(down_data, key=lambda x: x[2], reverse=True)

    #写入提产井
    up_body = "第一批优先提产井：\n|井号|当前配产值|可提产量|井类型|\n|--|--|--|--|\n"
    for x in up_data1:
        up_body = up_body + "|" + "|".join(map(str, x)) + "|\n"
    up_body = up_body + "第二批优先提产井：\n|井号|当前配产值|可提产量|井类型|\n|--|--|--|--|\n"
    for x in up_data2:
        up_body = up_body + "|" + "|".join(map(str, x)) + "|\n"
    with open("up_res.txt", "w") as f:
        f.write(up_body)
    #写入降产井
    down_body = "|井号|当前配产值|可降产量|井类型|\n|--|--|--|--|\n"
    for x in down_data:
        down_body = down_body + "|" + "|".join(map(str, x)) + "|\n"
    with open("down_res.txt", "w") as f:
        f.write(down_body)
get_new_info()
def main():
    app = FastAPI()
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

    @app.get("/get-data")
    async def start_detection():
        """
        触发式查询实时数据，计算并缓存内容
        """
        get_new_info()
        return {"status": 200, "message": "success"}

    @app.get("/get-info")
    async def get_data1():
        """
        获取配产相关信息
        """
        with open("up_res.txt", "r") as f:
            res = f.read()
        return {"data": res}

    @app.get("/get-down-info")
    async def get_data2():
        """
        获取降产相关信息
        """
        with open("down_res.txt", "r") as f:
            res = f.read()
        return {"data": res}

    @app.get("/get-cookie")
    async def get_cook():
        """
        获取cookie相关信息
        """
        with open("cookie.txt", "r") as f:
            cookie = f.read()
        return {"cookie": cookie}

    @app.post("/update-cookie")
    async def update_cook():
        """
        获取cookie相关信息
        """
        jsessionid = requests.post('http://10.84.4.74/yyqer/login.jsp',
                                   data={'name': 'wlx2023.jhyt',
                                         'pwd': '65154E8BFDC8C394424E31A390816707047B38D16805AD551D36D9862A3003C6'},
                                   verify=False).cookies.get_dict()['JSESSIONID']
        cookie = f'userName=wlx2023.jhyt; password=; JSESSIONID={jsessionid}'
        with open("cookie.txt", "w") as f:
            f.write(cookie)

        return {"status": 200, "message": "success"}

    return app


if __name__ == "__main__":
    app = main()
    api_host = os.environ.get("API_HOST", "0.0.0.0")
    api_port = int(os.environ.get("API_PORT", "8112"))
    uvicorn.run(app, host=api_host, port=api_port, log_config={
            "version": 1,
            "formatters": {
                "default": {
                    "()": "uvicorn.logging.DefaultFormatter",
                    "fmt": "%(asctime)s - %(levelprefix)s %(message)s",
                    "datefmt": "%Y-%m-%d %H:%M:%S",
                },
            },
            "handlers": {
                "default": {
                    "formatter": "default",
                    "class": "logging.StreamHandler",
                    "stream": "ext://sys.stderr",
                },
            },
            "loggers": {
                "uvicorn": {"handlers": ["default"], "level": "INFO"},
            },
        })
